<script setup lang="ts">
import { menuColumns, formItems, defaultData, levelOptions } from './table-data';
import { ChooseIcon } from '@/components/basic/icon';
import DynamicTable, { TableController } from '@/components/core/dynamic-table';
import { createDTableOptions, useTableData } from '@/components/core/dynamic-table/helper';
import { ElCascader, ElSwitch, ElSelect, ElInput } from 'element-plus';
import type { CascaderValue } from 'element-plus';
import { SchemaForm } from '@/components/core/schema-form';
import { ref, computed } from 'vue';
import { DefaultService as Api } from '@/servers';
import { ADialogInstance } from '@/components/basic/dialog';
import { message } from '@/components/basic/message';
import { AOptions } from '@/components/basic/select';

defineOptions({
  name: 'menu-list'
});

const columns = ref(menuColumns);

const { tableData, loading, fetchData } = useTableData();

const draggableOptions = createDTableOptions({}, columns);

type optionsType = {
  value: string | number;
  label: string;
  children: optionsType[];
};

const getOptions = (data: Partial<API.MenuItem>[]): optionsType[] => {
  return data.map(item => ({
    value: item.id as number,
    label: item.name as string,
    children: item.children ? getOptions(item.children) : ([] as optionsType[])
  }));
};

const pidOptions = computed(() => {
  return getOptions(tableData.value);
});

const dialogVisible = ref(false);
const form = ref<Partial<API.MenuItem>>({});

const dialogRef = ref<ADialogInstance>();

const openDialog = (row: Partial<API.MenuItem> = defaultData) => {
  const { children: _, ...rest } = row;
  form.value = rest;
  cascaderValue.value = form.value.pid || 0;
  dialogVisible.value = true;
  dialogRef.value?.openModel();

  return _;
};

const cascaderValue = ref(0);
const setCasCaderValue = (val: CascaderValue) => {
  form.value.pid = typeof val === 'number' ? val : (val[val.length - 1] as number);
};

const submitEditMenu = async (row = form.value) => {
  const { children: _c, menuName: _m, ...rest } = row;

  await Api.postSystemMenuEdit(rest as any);
  message.success('Edit success');
  await fetchData();
  return [_c, _m];
};

const deleteMenu = async (row: Partial<API.MenuItem>) => {
  await Api.postSystemMenuDelete(row.id as number);
  message.success('Delete success');
  await fetchData();
  return true;
};

const showIconChooser = ref(false);
</script>
<template>
  <div class="wh-full flex flex-col box-border pb-2">
    <TableController background="transparent">
      <template #right>
        <a-button type="primary" @click="openDialog()">Add Menu</a-button>
      </template>
    </TableController>
    <div class="overflow-y-auto w-full p-1 box-border" style="background-color: var(--el-bg-color)">
      <DynamicTable
        height="100%"
        :columns="columns as any"
        :default-expand-all="false"
        row-key="id"
        :data="tableData"
        v-loading="loading"
        show-overflow-tooltip
        header-row-class-name="table-header"
        :options="draggableOptions"
      >
        <template #status="container">
          <ElSwitch
            class="ml-2"
            :modelValue="Boolean(container.scope.row.status)"
            @change="val => ((container.scope.row.status = val ? 1 : 0) || true) && submitEditMenu(container.scope.row)"
            style="--el-switch-on-color: #13ce66"
          />
        </template>
        <template #operate="container">
          <a-button type="primary" @click="openDialog(container.scope.row)">Edit</a-button>
          <a-button type="danger" @click="deleteMenu">Delete</a-button>
        </template>
      </DynamicTable>

      <a-dialog ref="dialogRef" title="Edit Menu" width="600" @confirm="submitEditMenu" draggable>
        <SchemaForm :formItems="formItems" :model="form" label-width="60px" label-position="left">
          <template #pid>
            <el-cascader
              class="w-full"
              v-model="cascaderValue"
              :props="{ checkStrictly: true }"
              :options="pidOptions"
              @change="setCasCaderValue"
            >
            </el-cascader>
          </template>
          <template #level>
            <el-select v-model="form.level">
              <AOptions :options="levelOptions" />
            </el-select>
          </template>
          <template #status>
            <el-switch v-model="form.status" :active-value="1" :inactive-value="0" />
          </template>
          <template #icon>
            <div class="w-full flex flex-row gap-1" :class="showIconChooser ? 'mb-2' : ''">
              <el-input class="flex-1" v-model="form.icon" placeholder="choose icon" />
              <a-button type="primary" @click="showIconChooser = !showIconChooser">{{
                showIconChooser ? 'close' : 'choose'
              }}</a-button>
            </div>
            <ChooseIcon v-show="showIconChooser" @change="val => (form.icon = val)" />
          </template>
        </SchemaForm>
      </a-dialog>
    </div>
  </div>
</template>
